﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace MaterialEditor
{
    public class TesselateNode : Node
    {
        private NodeValue _result;
        public override NodeValue Result
        {
            get { return _result; }
        }

        private NodeValueType[][] _acceptTypes;
        public override NodeValueType[][] acceptTypes
        {
            get { return _acceptTypes; }
        }

        public override object Clone()
        {
            TesselateNode n = new TesselateNode((int)position.X, (int)position.Y);
            n._result = new NodeValue(_result);

            return n;
        }

        private InputSlot TextureSlot
        {
            get { return input[0]; }
        }

        private InputSlot ammountXSlot
        {
            get { return input[1]; }
        }

        private InputSlot ammountYSlot
        {
            get { return input[2]; }
        }

        public TesselateNode(int x, int y)
            : base(x, y)
        {
            input = new InputSlot[]
            {
                new InputSlot(this, null, "A"),
                new InputSlot(this, null, "Tile X"),
                new InputSlot(this, null, "Tile Y"),
            };

            TextureSlot.Connected += TextureSlot_Connected;
            ammountXSlot.Connected += ammountXSlot_Connected;
            ammountYSlot.Connected += ammountYSlot_Connected;

            TextureSlot.Disconnected += TextureSlot_Disconnected;
            ammountXSlot.Disconnected += ammountXSlot_Disconnected;
            ammountYSlot.Disconnected += ammountYSlot_Disconnected;


            TextureSlot.ValueChanged += UpdateValue;
            ammountXSlot.ValueChanged += UpdateValue;
            ammountYSlot.ValueChanged += UpdateValue;

            _acceptTypes = new NodeValueType[][]
            {
                new NodeValueType[] { NodeValueType.ValueTexture },
                new NodeValueType[] { NodeValueType.ValueFloat },
                new NodeValueType[] { NodeValueType.ValueFloat },
            };

            Name = "Tesselate";

            output = new InputSlot(this, null, "");
        }

        void ammountYSlot_Disconnected()
        {
            ammountYSlot.ValueChanged -= UpdateValue;
            ammountYSlot.value.TimeChanged -= UpdateTime;

            UpdateValue();
        }

        void ammountXSlot_Disconnected()
        {
            ammountXSlot.ValueChanged -= UpdateValue;
            ammountXSlot.value.TimeChanged -= UpdateTime;

            UpdateValue();
        }

        void TextureSlot_Disconnected()
        {
            TextureSlot.ValueChanged -= UpdateValue;

            UpdateValue();
        }

        void ammountYSlot_Connected()
        {
            ammountYSlot.ValueChanged += UpdateValue;
            ammountYSlot.value.TimeChanged += UpdateTime;

            UpdateValue();
        }

        void ammountXSlot_Connected()
        {
            ammountXSlot.ValueChanged += UpdateValue;
            ammountXSlot.value.TimeChanged += UpdateTime;

            UpdateValue();
        }

        void TextureSlot_Connected()
        {
            TextureSlot.ValueChanged += UpdateValue;

            UpdateValue();
        }

        private Tesselate t;

        private void UpdateValue()
        {
            if (!TextureSlot.isConnected || !(ammountXSlot.isConnected || ammountYSlot.isConnected))
            {
                _result = null;
                return;
            }

            TextureContainer container = new TextureContainer(TextureSlot.value.AsTexture2D());
            t = new Tesselate();
            t.TileWidth = ammountXSlot.isConnected ? (int)ammountXSlot.value.AsFloat() : 0;
            t.TileHeight = ammountYSlot.isConnected ? (int)ammountYSlot.value.AsFloat() : 0;

            container.texture.effects += t;

            _result = new NodeValue(container);
        }

        private void UpdateTime()
        {
            if (!TextureSlot.isConnected || !(ammountXSlot.isConnected || ammountYSlot.isConnected))
                return;

            t.TileWidth = ammountXSlot.isConnected ? (int)ammountXSlot.value.AsFloat() : 0;
            t.TileHeight = ammountYSlot.isConnected ? (int)ammountYSlot.value.AsFloat() : 0;
        }
    }
}